package com.tanhua.service;

import com.tanhua.dao.AnalysisByDayMapper;
import com.tanhua.domain.SummaryVo;
import com.tanhua.domain.YearAmountVo;
import com.tanhua.domain.YearVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

@Service
public class PanelService {
    @Autowired
    private AnalysisByDayMapper analysisByDayMapper;

    long oneDay = 1000 * 60 * 60 * 24; // 1天

    long yearMilli = oneDay * 365;  //1年

    public SummaryVo getSummary() {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = sdf.format(date);
        long time = date.getTime();

        Integer sumOfAllTheRegistered = checkNull(analysisByDayMapper.sumOfAllTheRegistered());    //累计用户
        Integer registeredByDay = checkNull(analysisByDayMapper.registeredByDay(dateStr));         //今日新增用户

        int active7Days = getActiveNum(time, 7);          //过去7天活跃用户
        int active30Days = getActiveNum(time, 30);        //过去30天活跃用户
        Integer activeToday = checkNull(analysisByDayMapper.activeByDay(dateStr));//今天的活跃用户
        Integer loginToday = checkNull(analysisByDayMapper.loginByDay(dateStr));   //今天登录次数

        long oneDay = 1000 * 60 * 60 * 24;
        String yesterdayStr = sdf.format(new Date(date.getTime() - oneDay));
        Integer registerYesterday = checkNull(analysisByDayMapper.registeredByDay(yesterdayStr));
        Integer loginYesterday = checkNull(analysisByDayMapper.loginByDay(yesterdayStr));
        Integer activeYesterday = checkNull(analysisByDayMapper.activeByDay(yesterdayStr));

        int registerRate = (int) (registerYesterday == 0 ? registeredByDay * 100 : ((registeredByDay.doubleValue() - registerYesterday.doubleValue()) / registerYesterday.doubleValue() * 100));  //今日新增用户涨跌率，单位百分数，正数为涨，负数为跌
        int loginRate = (int) (loginYesterday == 0 ? loginToday * 100 : ((loginToday.doubleValue() - loginYesterday.doubleValue()) / loginYesterday.doubleValue() * 100));  //今日登录次数涨跌率
        int activeRate = (int) (activeYesterday == 0 ? activeToday * 100 : ((activeToday.doubleValue() - activeYesterday.doubleValue()) / activeYesterday.doubleValue() * 100)); //今日活跃用户涨跌率

        SummaryVo summaryVo = new SummaryVo(sumOfAllTheRegistered, active30Days, active7Days, registeredByDay,
                registerRate, loginToday, loginRate, activeToday, activeRate);

        return summaryVo;
    }

    //计算过去n天的活跃用户数
    private int getActiveNum(long time, int days) {
        int activeSumByDays = 0;
        for (int i = 1; i <= days; i++) {
            time -= oneDay;  //过去1天、2天 ... 7天，查询每天的数据
            Date searchDate = new Date(time);
            String format = new SimpleDateFormat("yyyy-MM-dd").format(searchDate);
            Integer active = checkNull(analysisByDayMapper.activeByDay(format));

            activeSumByDays += checkNull(active);
        }
        return activeSumByDays;
    }

    //检查空指针
    private int checkNull(Integer integer) {
        if (integer == null)
            integer = 0;
        return integer;
    }


    public YearAmountVo getUserChartsData(Long start, Long end, Integer type) {
        YearAmountVo yearAmountVo;
        switch (type) {
            case 101:
                yearAmountVo = getNewUsersData(start, end);
                break;        //新增用户

            case 102:
                yearAmountVo = getActiveData(start, end);
                break;          //活跃用户

            case 103:
                yearAmountVo = getRetentionData(start, end);
                break;       //留存用户

            default:
                yearAmountVo = new YearAmountVo();
        }
        return yearAmountVo;
    }

    //获取新增用户数量，今年和去年这段时间的，分别按天封装
    public YearAmountVo getNewUsersData(long start, long end) {
        List<YearVo> thisYear = registeredList(start, end);
        List<YearVo> lastYear = registeredList(start - yearMilli, end - yearMilli);
        YearAmountVo yearAmountVo = new YearAmountVo();
        yearAmountVo.setThisYear(thisYear);
        yearAmountVo.setLastYear(lastYear);
        return yearAmountVo;
    }

    private List<YearVo> registeredList(long start, long end) {
        SimpleDateFormat sdf = new SimpleDateFormat("MM-dd");

        List<YearVo> vos = new LinkedList<>();
        for (end += oneDay; end > start; end -= oneDay) {
            Date date = new Date(end);
            int registeredNum = checkNull(analysisByDayMapper.registeredByDay(new SimpleDateFormat("yyyy-MM-dd").format(date)));
            YearVo yvo = new YearVo();
            yvo.setTitle(sdf.format(date));
            yvo.setAmount(registeredNum);
            vos.add(yvo);
        }
        return vos;
    }

    //今年的这一段时间  、 和去年这一段时间，分别按天封装
    public YearAmountVo getActiveData(long start, long end) {

        List<YearVo> thisYear = activeList(start, end);
        List<YearVo> lastYear = activeList(start - yearMilli, end - yearMilli);
        YearAmountVo yearAmountVo = new YearAmountVo();
        yearAmountVo.setThisYear(thisYear);
        yearAmountVo.setLastYear(lastYear);
        return yearAmountVo;
    }

    //今年的这一段时间  、按天封装
    private List<YearVo> activeList(long start, long end) {
        SimpleDateFormat sdf = new SimpleDateFormat("MM-dd");

        List<YearVo> vos = new LinkedList<>();
        for (end += oneDay; end > start; end -= oneDay) {
            int activeNum = getActiveNum(end, 1);
            YearVo yvo = new YearVo();
            yvo.setTitle(sdf.format(new Date(end)));
            yvo.setAmount(activeNum);
            vos.add(yvo);
        }
        return vos;
    }

    //获取用户留存的数据，今年和去年这段时间的，分别按天封装
    public YearAmountVo getRetentionData(long start, long end) {
        List<YearVo> thisYear = retentionList(start, end);
        List<YearVo> lastYear = retentionList(start - yearMilli, end - yearMilli);
        YearAmountVo vo = new YearAmountVo();
        vo.setThisYear(thisYear);
        vo.setLastYear(lastYear);
        return vo;
    }

    private List<YearVo> retentionList(long start, long end) {
        SimpleDateFormat sdf = new SimpleDateFormat("MM-dd");

        List<YearVo> vos = new LinkedList<>();
        for (end += oneDay; end > start; end -= oneDay) {
            Date date = new Date(end);
            int retentionNum = checkNull(analysisByDayMapper.retentionByDay(new SimpleDateFormat("yyyy-MM-dd").format(date)));
            YearVo yvo = new YearVo();
            yvo.setTitle(sdf.format(date));
            yvo.setAmount(retentionNum);
            vos.add(yvo);
        }
        return vos;
    }
}
